package cn.yywd_123.biliarchiver.account;

import cn.yywd_123.biliarchiver.utils.HttpsResponse;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class Session implements Serializable {
	public static final Path PATH = new File("cfg/session").toPath();
	public static Session current;

	static {
		Runtime.getRuntime().addShutdownHook(new Thread(Session::onShutDown));

		if (!PATH.toFile().exists()) {
			System.out.println("账号凭据将被存储在" + PATH.toAbsolutePath() + ",请妥善保存");

			try {
				PATH.getParent().toFile().mkdir();
				PATH.toFile().createNewFile();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}

	List<String> cookies = new ArrayList<>();
	transient UserInfo userInfo;

	Session() {

	}

	public static void loadSession() {
		try (ObjectInputStream stream = new ObjectInputStream(Files.newInputStream(PATH))) {
			current = (Session) stream.readObject();
		} catch (Exception e) {
			current = new Session();
		}

		current.load();
	}

	static void loginWithQrCode() throws Exception {
		if (!current.cookies.isEmpty()) return;

		JsonObject qrCodeData = JsonParser.parseString(HttpsResponse.GET("https://passport.bilibili.com/x/passport-login/web/qrcode/generate")).getAsJsonObject().getAsJsonObject("data");

		String url = "https://api.qrserver.com/v1/create-qr-code/?data=" + URLEncoder.encode(qrCodeData.get("url").getAsString(), "UTF-8");

		System.out.println("请在3分钟内访问下面的网址并扫描登陆 \n[" + url + "]");

		int i = 180;
		while (i-- > 0) {
			TimeUnit.SECONDS.sleep(1);
			JsonObject loginRequest = JsonParser.parseString(HttpsResponse.GET("https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=" + qrCodeData.get("qrcode_key").getAsString())).getAsJsonObject().getAsJsonObject("data");

			if (loginRequest.get("code").getAsInt() == 0) {
				System.out.println("登录成功!");
				return;
			}
		}
	}

	static void onShutDown() {
		try (ObjectOutputStream stream = new ObjectOutputStream(Files.newOutputStream(PATH))) {
			stream.writeObject(current);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	void verifyCookie() {
		if (!cookies.isEmpty()) {
			JsonObject refreshInfo = JsonParser.parseString(HttpsResponse.GET("https://passport.bilibili.com/x/passport-login/web/cookie/info")).getAsJsonObject();

			if (refreshInfo.get("code").getAsInt() == 0 && !refreshInfo.getAsJsonObject("data").get("refresh").getAsBoolean())
				return;
		}

		try {
			loginWithQrCode();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	void load() {
		verifyCookie();

		userInfo = new UserInfo();

		System.out.printf("欢迎,%s(mid=%d)\n", userInfo.getNickName(), userInfo.getMid());
	}

	public String getCookies() {
		StringBuilder buf = new StringBuilder();

		for (String cookie : cookies) {
			buf.append(cookie).append(" ");
		}

		return buf.toString();
	}

	public void addCookie(String cookie) {
		this.cookies.add(cookie);
	}

	public void clearCookie() {
		this.cookies.clear();
	}

	public UserInfo getUserInfo() {
		return userInfo;
	}

	public static class UserInfo {
		String nickName;
		int mid;

		UserInfo() {
			JsonObject data = JsonParser.parseString(HttpsResponse.GET("https://api.bilibili.com/x/member/web/account")).getAsJsonObject().getAsJsonObject("data");

			this.nickName = data.get("uname").getAsString();
			this.mid = data.get("mid").getAsInt();
		}

		public String getNickName() {
			return nickName;
		}

		public int getMid() {
			return mid;
		}
	}
}
